/**
 * @ClassName:
 * @author:
 * @Description:
 * @Date
 **/
//二分查找树
public class BinaryTree<E extends Comparable<E>> {
    private class Node {
        E e;
        Node left;
        Node right;

        public Node(E e) {
            this.e = e;
            left = null;
            right = null;
        }
    }

    private Node root;
    private int size;

    public BinaryTree() {
        root = null;
        size = 0;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public void add(E e) {
        if (root == null) {
            root = new Node(e);
            size++;
        } else {
            add(root, e);
        }
    }

    private Node add(Node root, E e) {
        if (root == null) {
            size++;
            return new Node(e);
        }
        if (e.compareTo(root.e) < 0) {
            //接上左子树
            root.left = add(root.left, e);
        } else if (e.compareTo(root.e) > 0) {
            //接上右子树
            root.right = add(root.right, e);
        }
        return root;
    }

    public boolean contains(E e) {
        return contains(root, e);
    }

    //查询元素是否存在
    private boolean contains(Node root, E e) {
        if (root == null) {
            return false;
        }
        if (e.compareTo(root.e) == 0) {
            return true;
        } else if (e.compareTo(root.e) < 0) {
            //找左子树里有没有
            return contains(root.left, e);
        } else {
            //找右子树里有没有
            return contains(root.right, e);
        }
    }

    //前序遍历
    public void preOrder() {
        preOrder(root);
    }

    private void preOrder(Node root) {
        if (root != null) {
            System.out.println(root.e);
            preOrder(root.left);
            preOrder(root.right);
        }
    }

    //中序遍历
    public void midOrder() {
        midOrder(root);
    }

    private void midOrder(Node root) {
        if (root == null) {
            return;
        }
        midOrder(root.left);
        System.out.println(root.e);
        midOrder(root.right);

    }

    //后序遍历
    public void postOrder() {
        postOrder(root);
    }

    private void postOrder(Node root) {
        if (root == null) {
            return;
        }
        postOrder(root.left);
        postOrder(root.right);
        System.out.println(root.e);
    }

    //二分查找树中的最小值
    public E minimum() {
        if (size == 0) {
            throw new IllegalArgumentException("no element");
        }
        return minimum(root).e;
    }

    //找出最小的节点
    private Node minimum(Node root) {
        if (root.left == null) {
            return root;
        }
        return minimum(root.left);
    }

    //二分查找树中的最大值
    public E maximum() {
        if (size == 0) {
            throw new IllegalArgumentException("no element");
        }
        return maximum(root).e;
    }

    //找出最大的节点
    private Node maximum(Node root) {
        if (root.right == null) {
            return root;
        }
        return maximum(root.right);
    }

    //从二分查找树中删除最小值的节点，返回最小值
    public E removeMin() {
        E result = minimum();
        root = removeMin(root);
        return result;
    }

    private Node removeMin(Node root) {
        //如果没有左孩子了，代表这个节点就是最小的了
        if (root.left == null) {
            //保存右节点
            Node rightNode = root.right;
            //删掉原先的右孩子
            root.right = null;
            size--;
            //作为上层节点的左孩子返回
            return rightNode;
        }
        root.left = removeMin(root.left);
        return root;
    }

    //从二分查找树中删除最大值的节点，返回最大值
    public E removeMax() {
        E result = maximum();
        root = removeMax(root);
        return result;
    }

    private Node removeMax(Node root) {
        //如果没有右孩子了，代表这个节点就是最大的了
        if (root.right == null) {
            //保存左节点
            Node leftNode = root.left;
            //删除原先的左孩子
            root.left = null;
            size--;
            //作为上层节点的右孩子返回
            return leftNode;
        }
        root.right = removeMax(root.right);
        return root;
    }

    public void remove(E e) {
        remove(root, e);
    }

    //删除以node为根的二分搜索树中值为e的节点，递归实现
    //返回删除后新的
    private Node remove(Node root, E e) {
        if (root == null) {
            return null;
        }
        if (e.compareTo(root.e) > 0) {
            root.right = remove(root.right, e);
            return root;
        } else if (e.compareTo(root.e) < 0) {
            root.left = remove(root.left, e);
            return root;
        } else {
            if (root.left == null) {
                Node rightNode = root.right;
                root.right = null;
                size--;
                return rightNode;
            }
            if (root.right == null) {
                Node leftNode = root.left;
                root.left = null;
                size--;
                return leftNode;
            }
            Node successor = minimum(root.right);
            successor.right = removeMin(root.right);
            successor.left = root.left;
            root.left = root.right = null;
            return successor;
        }
    }
}
